#include "ota.h"
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <esp_http_client.h>
#include <esp_crt_bundle.h>
#include <bsp.h>
#include <esp_log.h>
#include <cJSON.h>
#include "mutable_buffer.h"


#define TAG "OTA"

static esp_err_t _http_event_handler(esp_http_client_event_t *evt)
{
    mutable_buffer_t *buffer = evt->user_data;
    switch (evt->event_id)
    {
    case HTTP_EVENT_ERROR:
        ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
        break;
    case HTTP_EVENT_ON_CONNECTED:
        ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
        break;
    case HTTP_EVENT_HEADER_SENT:
        ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
        break;
    case HTTP_EVENT_ON_HEADER:
        ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
        break;
    case HTTP_EVENT_ON_DATA:
        ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
        // 可能需要数据拼接
        mutable_buffer_append(buffer, evt->data, evt->data_len);
        break;
    case HTTP_EVENT_ON_FINISH:
        ESP_LOGI(TAG, "Response received: %s", mutable_buffer_get_buffer(buffer));
        break;
    case HTTP_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
        break;
    case HTTP_EVENT_REDIRECT:
        ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT");
        break;
    }
    return ESP_OK;
}

ota_t *ota_create()
{
    ota_t *ota = malloc(sizeof(ota_t));
    assert(ota);
    memset(ota, 0, sizeof(ota_t));
    return ota;
}

void ota_free(ota_t *ota)
{
    if (ota->activation_code)
    {
        free(ota->activation_code);
    }

    if (ota->chanllege)
    {
        free(ota->chanllege);
    }

    if (ota->message)
    {
        free(ota->message);
    }

    free(ota);
}

void ota_check_new_version(ota_t *ota)
{
    // 发一个post http请求
    mutable_buffer_t *buffer = mutable_buffer_create();
    esp_http_client_config_t config = {
        .url = OTA_URL,
        .method = HTTP_METHOD_POST,
        .event_handler = _http_event_handler,
        .user_data = buffer,
        .crt_bundle_attach = esp_crt_bundle_attach,
    };

    // 创建一个http客户端
    esp_http_client_handle_t client = esp_http_client_init(&config);
    assert(client);

    // 添加Header
    esp_http_client_set_header(client, "Content-Type", "application/json");
    esp_http_client_set_header(client, "Accept", "application/json");
    esp_http_client_set_header(client, "Client-Id", bsp_get_uuid());
    esp_http_client_set_header(client, "Device-Id", bsp_get_mac_address());
    esp_http_client_set_header(client, "Accept-Language", "zh-CN");
    esp_http_client_set_header(client, "User-Agent", "bread-compact_wifi/1.0.0");

    // 添加post body
    char *bsp_json = bsp_get_json();
    esp_http_client_set_post_field(client, bsp_json, strlen(bsp_json));
    
    // 发送请求
    esp_http_client_perform(client);
    free(bsp_json);

    // 解析激活码部分
    if (esp_http_client_get_status_code(client) != 200)
    {
        ESP_LOGE(TAG, "Failed to send request");
        goto END;
    }

    cJSON* root = cJSON_Parse(mutable_buffer_get_buffer(buffer));
    if (!root)
    {
        ESP_LOGE(TAG, "Failed to parse JSON");
        goto END;
    }
    

    cJSON* activation_obj = cJSON_GetObjectItem(root, "activation");
    if (activation_obj)
    {
        ota->has_activation_code = true;
        cJSON* activation_code = cJSON_GetObjectItem(activation_obj, "code");
        assert(cJSON_IsString(activation_code));
        cJSON* challenge = cJSON_GetObjectItem(activation_obj, "challenge");
        assert(cJSON_IsString(challenge));
        cJSON* message = cJSON_GetObjectItem(activation_obj, "message");
        assert(cJSON_IsString(message));

        ota->activation_code = strdup(activation_code->valuestring);
        ota->chanllege = strdup(challenge->valuestring);
        ota->message = strdup(message->valuestring);
    }
    cJSON_Delete(root);

END:
    // 清理客户端
    mutable_buffer_free(buffer);
    esp_http_client_cleanup(client);
}
